home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 4 / Example 4.6 / terrain.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-01  |  5.3 KB  |  226 lines

  1. #include "terrain.h"
  2.  
  3. const DWORD TERRAINVertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
  4.  
  5. //////////////////////////////////////////////////////////////////////////////////////////
  6. //                                    PATCH                                                //
  7. //////////////////////////////////////////////////////////////////////////////////////////
  8.  
  9. PATCH::PATCH()
  10. {
  11.     m_pDevice = NULL;
  12.     m_pMesh = NULL;
  13. }
  14. PATCH::~PATCH()
  15. {
  16.     Release();
  17. }
  18.  
  19. void PATCH::Release()
  20. {
  21.     if(m_pMesh != NULL)
  22.         m_pMesh->Release();
  23.     m_pMesh = NULL;
  24. }
  25.  
  26. HRESULT PATCH::CreateMesh(HEIGHTMAP &hm, RECT source, IDirect3DDevice9* Dev)
  27. {
  28.     if(m_pMesh != NULL)
  29.     {
  30.         m_pMesh->Release();
  31.         m_pMesh = NULL;
  32.     }
  33.  
  34.     try
  35.     {
  36.         m_pDevice = Dev;
  37.  
  38.         int width = source.right - source.left;
  39.         int height = source.bottom - source.top;
  40.         int nrVert = (width + 1) * (height + 1);
  41.         int nrTri = width * height * 2;
  42.  
  43.         if(FAILED(D3DXCreateMeshFVF(nrTri, nrVert, D3DXMESH_MANAGED, TERRAINVertex::FVF, m_pDevice, &m_pMesh)))
  44.         {
  45.             debug.Print("Couldn't create mesh for PATCH");
  46.             return E_FAIL;
  47.         }
  48.  
  49.         //Create vertices
  50.         TERRAINVertex* ver = 0;
  51.         m_pMesh->LockVertexBuffer(0,(void**)&ver);
  52.         for(int z=source.top, z0 = 0;z<=source.bottom;z++, z0++)
  53.             for(int x=source.left, x0 = 0;x<=source.right;x++, x0++)
  54.             {
  55.                 D3DXVECTOR3 pos = D3DXVECTOR3(x, hm.m_pHeightMap[x + z * hm.m_size.x], -z);
  56.  
  57.                 //Strect UV coordinates once over the entire terrain
  58.                 D3DXVECTOR2 uv = D3DXVECTOR2(x / (float)hm.m_size.x, z / (float)hm.m_size.y);
  59.  
  60.                 ver[z0 * (width + 1) + x0] = TERRAINVertex(pos, uv);
  61.             }
  62.         m_pMesh->UnlockVertexBuffer();
  63.  
  64.         //Calculate Indices
  65.         WORD* ind = 0;
  66.         m_pMesh->LockIndexBuffer(0,(void**)&ind);    
  67.         int index = 0;
  68.  
  69.         for(int z=source.top, z0 = 0;z<source.bottom;z++, z0++)
  70.             for(int x=source.left, x0 = 0;x<source.right;x++, x0++)
  71.             {
  72.                 //Triangle 1
  73.                 ind[index++] =   z0   * (width + 1) + x0;
  74.                 ind[index++] =   z0   * (width + 1) + x0 + 1;
  75.                 ind[index++] = (z0+1) * (width + 1) + x0;        
  76.  
  77.                 //Triangle 2
  78.                 ind[index++] = (z0+1) * (width + 1) + x0;
  79.                 ind[index++] =   z0   * (width + 1) + x0 + 1;
  80.                 ind[index++] = (z0+1) * (width + 1) + x0 + 1;
  81.             }
  82.  
  83.         m_pMesh->UnlockIndexBuffer();
  84.  
  85.         //Set Attributes
  86.         DWORD *att = 0, a = 0;
  87.         m_pMesh->LockAttributeBuffer(0,&att);
  88.         memset(att, 0, sizeof(DWORD)*nrTri);
  89.         m_pMesh->UnlockAttributeBuffer();
  90.  
  91.         //Compute normals
  92.         D3DXComputeNormals(m_pMesh, NULL);
  93.     }
  94.     catch(...)
  95.     {
  96.         debug.Print("Error in PATCH::CreateMesh()");
  97.         return E_FAIL;
  98.     }
  99.  
  100.     return S_OK;
  101. }
  102.  
  103. void PATCH::Render()
  104. {
  105.     //Draw mesh
  106.     if(m_pMesh != NULL)
  107.         m_pMesh->DrawSubset(0);
  108. }
  109.  
  110. //////////////////////////////////////////////////////////////////////////////////////////
  111. //                                    TERRAIN                                                //
  112. //////////////////////////////////////////////////////////////////////////////////////////
  113.  
  114. TERRAIN::TERRAIN()
  115. {
  116.     m_pDevice = NULL;
  117. }
  118.  
  119. void TERRAIN::Init(IDirect3DDevice9* Dev, INTPOINT _size)
  120. {
  121.     m_pDevice = Dev;
  122.     m_size = _size;
  123.     m_pHeightMap = NULL;
  124.  
  125.     //Load texture
  126.     if(FAILED(D3DXCreateTextureFromFile(Dev, "textures/diffusemap.jpg", &m_pTexture)))
  127.         debug.Print("Could not load diffusemap.jpg");
  128.  
  129.     //Initiate heightmap and texture
  130.     m_pHeightMap = new HEIGHTMAP(m_size, 20.0f);
  131.     m_pHeightMap->LoadFromFile(m_pDevice, "textures/heightmap.jpg");
  132.     CreatePatches(3);
  133.  
  134.     //Create white material    
  135.     m_mtrl.Ambient = m_mtrl.Specular = m_mtrl.Diffuse  = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f);
  136.     m_mtrl.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
  137. }
  138.  
  139. void TERRAIN::Release()
  140. {
  141.     for(int i=0;i<m_patches.size();i++)
  142.         if(m_patches[i] != NULL)
  143.             m_patches[i]->Release();
  144.  
  145.     m_patches.clear();
  146.  
  147.     if(m_pHeightMap != NULL)
  148.     {
  149.         m_pHeightMap->Release();
  150.         delete m_pHeightMap;
  151.         m_pHeightMap = NULL;
  152.     }
  153. }
  154.  
  155. void TERRAIN::GenerateRandomTerrain(int numPatches)
  156. {
  157.     try
  158.     {
  159.         Release();
  160.  
  161.         //Create two heightmaps and multiply them
  162.         m_pHeightMap = new HEIGHTMAP(m_size, 15.0f);
  163.         HEIGHTMAP hm2(m_size, 30.0f);
  164.  
  165.         m_pHeightMap->CreateRandomHeightMap(rand()%2000, 2.5f, 0.5f, 8);
  166.         hm2.CreateRandomHeightMap(rand()%2000, 2.5f, 0.7f, 3);
  167.  
  168.         hm2.Cap(hm2.m_maxHeight * 0.4f);
  169.  
  170.         *m_pHeightMap *= hm2;
  171.         hm2.Release();
  172.  
  173.         CreatePatches(numPatches);
  174.     }
  175.     catch(...)
  176.     {
  177.         debug.Print("Error in TERRAIN::GenerateRandomTerrain()");
  178.     }
  179. }
  180.  
  181. void TERRAIN::CreatePatches(int numPatches)
  182. {
  183.     try
  184.     {
  185.         //Clear any old patches
  186.         for(int i=0;i<m_patches.size();i++)
  187.             if(m_patches[i] != NULL)
  188.                 m_patches[i]->Release();
  189.         m_patches.clear();
  190.  
  191.         if(m_pHeightMap == NULL)return;
  192.  
  193.         //Create new m_patches
  194.         for(int y=0;y<numPatches;y++)
  195.             for(int x=0;x<numPatches;x++)
  196.             {
  197.                 RECT r = {x * (m_size.x - 1) / (float)numPatches, 
  198.                           y * (m_size.y - 1) / (float)numPatches, 
  199.                         (x+1) * (m_size.x - 1) / (float)numPatches,
  200.                         (y+1) * (m_size.y - 1) / (float)numPatches};
  201.                         
  202.                 PATCH *p = new PATCH();
  203.                 p->CreateMesh(*m_pHeightMap, r, m_pDevice);
  204.                 m_patches.push_back(p);
  205.             }
  206.     }
  207.     catch(...)
  208.     {
  209.         debug.Print("Error in TERRAIN::CreatePatches()");
  210.     }
  211. }
  212.  
  213. void TERRAIN::Render()
  214. {
  215.     //Set render states
  216.     m_pDevice->SetRenderState(D3DRS_LIGHTING, true);
  217.     m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);
  218.  
  219.     //Set Texture and Material
  220.     m_pDevice->SetMaterial(&m_mtrl);
  221.     m_pDevice->SetTexture(0, m_pTexture);
  222.  
  223.     //Render Patches
  224.     for(int i=0;i<m_patches.size();i++)
  225.         m_patches[i]->Render();
  226. }